/////////////////////////////////////////////////////////////////////////////
// Purpose:     Synchronization of resource access by processes and threads
// Author:      Jesus Gonzalez
// Modified by: 
// Copyright:   (c) 2003-2013 Jesus Gonzalez <jgonzalez@gdr-sistemas.com>
// License:     BSD License
/////////////////////////////////////////////////////////////////////////////

#ifndef _SMARTLIB_SEMAPHORE_H_
#define _SMARTLIB_SEMAPHORE_H_

/**
 * \file
 * Synchronization of resource access by processes and threads.
 */

#include <SmartLib/SmartPtr.h>
#include <SmartLib/ExtendedTypes.h>
#include <string>

///@defgroup proc_mgmt Process management
///@{

class SemaphorePrvSys;

/**
 * The Semaphore class can be used to synchronize and control the access to
 * resources by multiple processes and/or threads.
 */
class Semaphore : public SmartObject
{
public:
    DECLARE_SMARTPTR(Semaphore);

    /**
     * Named semaphore constructor.
     *
     * Named semaphores can be shared between different processes and/or threads.
     *
     * @param[in] name Unique name to identify the semaphore
     * @param[in] initialValue Value to which the semaphore will be initialized
     */
    Semaphore(const std::string &name, uint initialValue = 0);

    /**
     * Unnamed semaphore constructor.
     *
     * Unnamed semaphores can be shared between threads running in the same process.
     *
     * @param[in] initialValue Value to which the semaphore will be initialized
     */
    Semaphore(uint initialValue = 0);

    virtual ~Semaphore();

    /**
     * Holds (decrements / locks) the semaphore.
     *
     * If the semaphore's value is greater than zero, the operation succeeds and returns
     * immediately. Otherwise, the operation is blocked until the value is raised
     * above zero (i.e. another process or thread releases the semaphore).
     */
    void Hold();

    /**
     * Tries to hold (decrement / locks) the semaphore.
     *
     * If the semaphore's value is greater than zero, the operation succeeds.
     * Otherwise, the operation is unsuccessful. In any case, the function does not block.
     *
     * @return \p True if the semaphore could be hold, \p false otherwise.
     */
    bool TryHold();

    /**
     * Releases (increments / unlocks) the semaphore.
     *
     * If another process or thread was blocked in a locking call, it will unblock.
     */
    void Release();

    /**
     * Gets the current value of the semaphore.
     */
    int getValue();

private:
    SemaphorePrvSys* m_prvsys;
};

///@}

#endif // _SMARTLIB_SEMAPHORE_H_
